package de.ret_world.openrpgstudio.editor.gui;

import buoy.event.CommandEvent;
import buoy.event.WindowClosingEvent;
import buoy.widget.*;
import de.ret_world.openrpgstudio.editor.Configuration;
import de.ret_world.openrpgstudio.editor.Main;
import de.ret_world.openrpgstudio.editor.Project;
import de.ret_world.openrpgstudio.editor.helpers.Internationalization;
import de.ret_world.openrpgstudio.editor.plugininterfaces.OptionMenuPlugin;
import java.awt.Insets;
import java.awt.Rectangle;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.border.TitledBorder;
import org.apache.log4j.Logger;
import org.java.plugin.PluginClassLoader;
import org.java.plugin.PluginLifecycleException;
import org.java.plugin.PluginManager;
import org.java.plugin.registry.Extension;
import org.java.plugin.registry.ExtensionPoint;

/**
 * General Preferences Dialog. You can use the Plugin Extension "OptionMenu" to create a tab to show your option panel.
 *
 * @author Emu
 */
public class OptionsDialog {

    private BFrame parent;
    private BDialog dialog;
    private PluginManager manager;
    private Main main;
    private ArrayList<OptionMenuPlugin> optionPlugins;

    public OptionsDialog(BFrame parent, Main main) {
        this.parent = parent;
        this.optionPlugins = new ArrayList<>();
        this.main = main;
        this.manager = main.getManager();
    }

    /**
     * Shows the OptionDialog.
     */
    public void showDialog(PluginClassLoader cl) {
        Internationalization intn = Internationalization.getInstance();
        dialog = new BDialog(parent, intn.getString("MENU.APPOPTIONS"), true);

        BorderContainer bc = new BorderContainer();
        BTabbedPane tabs = new BTabbedPane();

        OptionMenuPlugin plugin = new AppOptionPane();
        optionPlugins.add(plugin);
        BScrollPane pluginContainer = new BScrollPane(BScrollPane.SCROLLBAR_NEVER, BScrollPane.SCROLLBAR_AS_NEEDED);
        plugin.init(pluginContainer);
        tabs.add(pluginContainer, intn.getString("OPTIONS.GENERAL"), new ImageIcon(cl.getResource("wrench-screwdriver.png")));

        //Plugin Extension Point "OptionMenu"
        if (Project.isProjectLoaded()) {
            ExtensionPoint toolExtPoint = manager.getRegistry().getExtensionPoint(Main.PLUGIN_ID, "OptionMenu");
            for (Extension ext : toolExtPoint.getConnectedExtensions()) {
                //initialize the plugin
                if (manager.isPluginEnabled(ext.getDeclaringPluginDescriptor())) {
                    try {
                        // Activate plug-in that declares extension.
                        manager.activatePlugin(ext.getDeclaringPluginDescriptor().getId());
                        main.reloadInternationalization();
                        // Get plug-in class loader.
                        ClassLoader classLoader = manager.getPluginClassLoader(ext.getDeclaringPluginDescriptor());
                        // Load Tool class.
                        Class<?> clazz = classLoader.loadClass(ext.getParameter("class").valueAsString());
                        // Create Tool instance.
                        plugin = (OptionMenuPlugin) clazz.newInstance();
                        optionPlugins.add(plugin);
                        pluginContainer = new BScrollPane(BScrollPane.SCROLLBAR_NEVER, BScrollPane.SCROLLBAR_AS_NEEDED);
                        // Initialize class instance according to interface contract.
                        plugin.init(pluginContainer);

                        String sicon = ext.getParameter("icon16").valueAsString();
                        if (sicon != null) {
                            URL uicon = classLoader.getResource(sicon);
                            if (uicon != null) {
                                Icon picon = new ImageIcon(uicon);
                                tabs.add(pluginContainer, ext.getParameter("name").valueAsString(), picon);
                                break;
                            }
                        }
                        tabs.add(pluginContainer, ext.getParameter("name").valueAsString());
                    } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | PluginLifecycleException ex) {
                        Logger.getLogger(OptionsDialog.class).error(ex);
                    }
                }
            }
        }

        bc.add(BOutline.createEtchedBorder(tabs, false), BorderContainer.CENTER, new LayoutInfo(LayoutInfo.CENTER, LayoutInfo.BOTH));

        LayoutInfo li = new LayoutInfo(LayoutInfo.WEST, LayoutInfo.HORIZONTAL, new Insets(5, 5, 5, 5), null);

        BorderContainer bc2 = new BorderContainer();
        BButton btn = new BButton(intn.getString("OK"));
        btn.addEventLink(CommandEvent.class, this, "ok");
        bc2.add(btn, BorderContainer.EAST, li);
        btn = new BButton(intn.getString("CANCEL"));
        btn.addEventLink(CommandEvent.class, this, "cancel");
        bc2.add(btn, BorderContainer.CENTER, li);
        bc.add(bc2, BorderContainer.SOUTH, new LayoutInfo(LayoutInfo.EAST, LayoutInfo.NONE, new Insets(5, 5, 5, 5), null));

        dialog.setContent(bc);
        dialog.addEventLink(WindowClosingEvent.class, this, "cancel");
        dialog.setBounds(new Rectangle(150, 150, 500, 500));
        dialog.setResizable(false);
        dialog.setVisible(true);
    }

    private void cancel() {
        dialog.dispose();
    }

    private void ok() {
        for (OptionMenuPlugin o : optionPlugins) {
            o.save();
        }

        dialog.dispose();
    }

    private class AppOptionPane extends OptionMenuPlugin {

        private BTextField txtUserName;
        private BTextField txtProjectName;
        private BTextField txtGameName;
        private BTextField txtGameVersion;
        private BComboBox cbLanguage;
        private BCheckBox cxLanguageReplace;
        private Project project;
        private Configuration config;

        @Override
        public void init(BScrollPane container) {
            Internationalization intn = Internationalization.getInstance();
            config = Configuration.getInstance(Main.PLUGIN_ID);

            ColumnContainer cc = new ColumnContainer();

            LayoutInfo li = new LayoutInfo(LayoutInfo.WEST, LayoutInfo.HORIZONTAL, new Insets(5, 5, 5, 5), null);

            ColumnContainer globalC = new ColumnContainer();
            globalC.add(new BLabel(intn.getString("OPTIONS.AUTHOR.NAME")), li);
            txtUserName = new BTextField(config.getProperty("user.name", System.getProperty("user.name")));
            globalC.add(txtUserName, li);
            globalC.add(new BLabel(intn.getString("OPTIONS.LANGUAGE")), li);

            //Getting all languages
            ArrayList<String> langs = new ArrayList<>();
            String s = config.getProperty("languages.lst", "eng");
            String[] sa = s.split(",");
            langs.addAll(Arrays.asList(sa));

            cbLanguage = new BComboBox(langs);
            cbLanguage.setSelectedValue(config.getProperty("window.language", "eng"));
            globalC.add(cbLanguage, li);

            cxLanguageReplace = new BCheckBox(intn.getString("OPTIONS.LANGUAGEREPLACE"), Boolean.valueOf(config.getProperty("window.language.replacenotfound", "true")));
            globalC.add(cxLanguageReplace, li);

            cc.add(new BOutline(globalC, new TitledBorder(intn.getString("OPTIONS.GLOBAL"))), li);

            if (Project.isProjectLoaded()) {
                project = Project.getInstance();

                ColumnContainer projectC = new ColumnContainer();
                projectC.add(new BLabel(intn.getString("NEW.PROJECTNAME")), li);
                txtProjectName = new BTextField(project.getConfig().getProperty("project.name"));
                projectC.add(txtProjectName, li);
                projectC.add(new BLabel(intn.getString("NEW.GAMENAME")), li);
                txtGameName = new BTextField(project.getConfig().getProperty("game.name"));
                projectC.add(txtGameName, li);
                projectC.add(new BLabel(intn.getString("OPTIONS.GAMEVERSION")), li);
                txtGameVersion = new BTextField(project.getConfig().getProperty("game.version"));
                projectC.add(txtGameVersion, li);
                cc.add(new BOutline(projectC, new TitledBorder(intn.getString("OPTIONS.PROJECT"))), li);
            }

            container.setContent(cc);
        }

        @Override
        public void save() {
            config.setProperty("user.name", txtUserName.getText());
            config.setProperty("window.language", (String) cbLanguage.getSelectedValue());
            config.setProperty("window.language.replacenotfound", Boolean.toString(cxLanguageReplace.getState()));
            config.storeConfig();

            if (Project.isProjectLoaded()) {
                project.getConfig().setProperty("project.name", txtProjectName.getText());
                project.getConfig().setProperty("game.name", txtGameName.getText());
                project.getConfig().setProperty("game.author", txtUserName.getText());
                project.getConfig().setProperty("game.version", txtGameVersion.getText());
                try {
                    project.save();
                } catch (IOException ex) {
                    Logger.getLogger(OptionsDialog.class).error(ex);
                }
            }
        }
    }
}
